package rkdwogus7.basic;

import java.util.ArrayList;

public class J22_Generic {
	
	public static void main(String[] args) {
		// 컬렉션 프레임워크를 구성하는 핵심 기술
		// 흔히, 타입 매개변수라고 불리우는 <E>, <K>, <V>등의 다이아몬드 기호를 이용하여
		// 컬렉션의 요소들을 [일반화]할 수 있음
		// 이것을 통해 엄격한 자료형 검사도 할 수 있고 불필요한 형변환도 방지할 수 있음
		J22_Tiger tiger = new J22_Tiger();
		J22_Lion lion = new J22_Lion();
		J22_Zibra zibra = new J22_Zibra();
		
		ArrayList zoo = new ArrayList();
		zoo.add(tiger);
		zoo.add(lion);
		zoo.add(zibra);
		
		// tiger = zoo.get(0);
		tiger = (J22_Tiger)zoo.get(0);
		// 우리에서 꺼낼 때 귀찮게도 형변환이 필요
		lion = (J22_Lion)zoo.get(1);
		zibra = (J22_Zibra)zoo.get(2);
		
		// 하지만, 아래의 문제가 발생할 수 있음!!
		// zibra = (J22_Zibra)zoo.get(0);	 : X
		// 실행을 해 보면 호랑이와 얼룩말이 충돌해서 오류가 남. 엄격한 자료형 검사를 하지 않은 것임
		// runtime error
		// 즉, 컴파일 단계에서 엄격한 자료형 검사를 하지 않았기 때문에 실행 시 오류가 표시됨
		
	/*---------------------------------------------------------------------*/
/*		ArrayList zoo = new ArrayList();
		zoo.add(tiger);
		zoo.add(lion);
		zoo.add(zibra);
		*/ // 이 배열에 문제가 있음. 잡다한 것들을 넣다 보니 빼 낼 때에도 어려움이 있음
		// 이래서 제네릭이 나오는 거야.
		// <E> : Element, 배열 요소의 자료형을 의미
		ArrayList<J22_Tiger> cage1 = new ArrayList<J22_Tiger>();
		ArrayList<J22_Lion> cage2 = new ArrayList<J22_Lion>();
		ArrayList<J22_Zibra> cage3 = new ArrayList<J22_Zibra>();
		// ArrayList에 타입 매개변수로 Tiger를 지정하면 해당 ArrayList에는
		// Tiger 객체만 저장 가능.
		
		cage1.add(tiger);
		// cage1.add(lion);
		// cage1.add(zibra);
		// cage1에 세 가지 타입의 동물들을 다 저장해 보는거야. 이렇게 하니까 오류가 나지?
		// 난 이런 식으로 남들은 다 쉽다고 하는 게 제일 어려워... 문제풀이 자꾸 해 보자.
		
		// 빼 내 보자. 이것도 나는 왜 어렵지... 
		tiger = cage1.get(0);
			// 불필요한 type casting 제거
		// lion = cage1.get(0);
			// 컴파일 시점에 자료형 불일치 오류 표시
		// 원노트에 써 놨지? 캐스팅이 사라졌고, 타입도 알려 줘.
		// 컴파일 전에 미리 알려 주기 때문에 개발자 입장에서 쉽지.
		
		// JDK 1.7 에서부터 추가된 기능은
		// ArrayList<J22_Tiger> cage1 = new ArrayList<>();
		// 이렇게도 가능해
		
		
		
	}

	
	
}

class J22_Tiger {
	public void howl() { System.out.println( "호랑이가 울어요" ); }
}

class J22_Lion {
	public void howl() { System.out.println( "사자가 울어요" ); }
}

class J22_Zibra {
	public void howl() { System.out.println( "얼룩말이 울어요" ); }
}

// 예전에는 컬렉션 사용 시 중구난방으로 마구 입력해 왔어. 문법적으로 오류는 없으나 실행 시 오류가 나오는 문제가 있었어
// 제네릭을 쓰면 그럴 확률을 최소화 할 수 있어. 개발자 입장에서는 시행착오를 최소화 할 수 있는거지
// 요즘은 객체의 묶음을 처리하는 방법으로 많이 사용하고 있으니 알아두도록 하시게.



